package com.yyx.service.impl;

import com.yyx.exception.BusinessException;
import com.yyx.pojo.entity.Package;
import com.yyx.pojo.request.package_.PackageUpdateRequest;
import com.yyx.repository.PackageRepository;
import com.yyx.service.FileService;
import com.yyx.service.PackageService;
import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.Icon;
import net.dongliu.apk.parser.bean.IconFace;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

@Service
public class PackageServiceImpl implements PackageService {

    @Autowired
    private PackageRepository packageRepository;

    @Autowired
    private FileService fileService;

    @Value("${file.upload-dir}")
    private String uploadDir;

    @Value("${file.base-url}")
    private String baseUrl;

    @Override
    public Page<Package> list(int page, int size) {
        return packageRepository.findAll(PageRequest.of(page, size));
    }

    @Override
    public Page<Package> searchByFileName(String query) {
        if (query == null || query.trim().isEmpty()) {
            return Page.empty();
        }
        List<Package> packageList = packageRepository.findAllByFileNameContainingIgnoreCase(query.trim());
        return new PageImpl<>(packageList);
    }

    @Override
    public Package getById(Long id) {
        return packageRepository.findById(id)
                .orElseThrow(() -> new BusinessException("安装包不存在"));
    }

    @Override
    public Package save(MultipartFile file, String version, String officialUrl) throws IOException {
        // 验证文件
        if (file == null || file.isEmpty()) {
            throw new BusinessException("上传文件不能为空");
        }

        // 使用 FileService 上传文件
        String uniqueFileName = fileService.upload(file);
        String originalFileName = file.getOriginalFilename() != null ? file.getOriginalFilename() : uniqueFileName;
        String suffix = originalFileName.lastIndexOf('.') >= 0 ? originalFileName.substring(originalFileName.lastIndexOf('.')) : "";

        // 提取图标（占位）
        String iconUrl = extractIconUrl(file);

        // 创建 Package 实体
        Package pkg = new Package();
        pkg.setFileName(originalFileName);
        pkg.setFilePath(uniqueFileName);
        pkg.setFileSize(file.getSize());
        pkg.setVersion(version);
        pkg.setSuffix(suffix);
        pkg.setIconUrl(iconUrl);
        pkg.setOfficialUrl(officialUrl);

        return packageRepository.save(pkg);
    }

    @Override
    public Package update(PackageUpdateRequest request) {
        Package entity = packageRepository.findById(request.getId())
                .orElseThrow(() -> new BusinessException("安装包不存在"));
        BeanUtils.copyProperties(request, entity);
        return packageRepository.save(entity);
    }

    @Override
    public void delete(Long id) {
        Package pkg = packageRepository.findById(id)
                .orElseThrow(() -> new BusinessException("安装包不存在"));
        fileService.delete(Paths.get(pkg.getFilePath()).getFileName().toString());
        packageRepository.deleteById(id);
    }

    private String extractIconUrl(MultipartFile file) throws IOException {
        String originalFileName = file.getOriginalFilename();
        if (originalFileName == null) {
            throw new BusinessException("安装包不存在");
        }

        String suffix = originalFileName.lastIndexOf('.') >= 0 ?
                originalFileName.substring(originalFileName.lastIndexOf('.')).toLowerCase() : "";

        // 创建 icons 目录
        Path iconsDir = Paths.get(uploadDir, "icons");
        if (!Files.exists(iconsDir)) {
            Files.createDirectories(iconsDir);
        }

        String iconFileName = UUID.randomUUID().toString() + ".png";
        Path iconPath = iconsDir.resolve(iconFileName);

        if (".apk".equals(suffix)) {
            // 处理 APK 文件
            Path tempFile = Files.createTempFile("apk", ".apk");
            try {
                // 保存临时文件
                Files.write(tempFile, file.getBytes());
                try (ApkFile apkFile = new ApkFile(tempFile.toFile())) {
                    List<IconFace> icons = apkFile.getAllIcons();
                    if (!icons.isEmpty()) {
                        IconFace icon = icons.get(0); // 选择第一个图标（通常为最高分辨率）
                        if (icon != null && icon.getData() != null) {
                            // 保存图标
                            Files.write(iconPath, icon.getData());
                            return baseUrl + iconFileName;
                        }
                    }
                }
            } catch (IOException e) {
                throw new BusinessException("APK 图标提取失败: " + e.getMessage());
            } finally {
                Files.deleteIfExists(tempFile);
            }
        } else if (".exe".equals(suffix)) {

            Path tempFile = Files.createTempFile("exe", ".exe");
            Files.write(tempFile, file.getBytes());
            try {
                CommandLine cmdLine = CommandLine.parse("wrestool -x -t 14 " + tempFile.toString() + " > " + iconPath.toString());
                DefaultExecutor executor = new DefaultExecutor();
                executor.execute(cmdLine);
                if (Files.exists(iconPath)) {
                    return baseUrl + iconPath.getFileName().toString();
                }
            } catch (Exception e) {
                throw new BusinessException("EXE 图标提取失败: " + e.getMessage());
            } finally {
                Files.deleteIfExists(tempFile);
            }
        }
        return null;
    }
}